package stock.nordnet;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

import misc.Helpers;
import misc.JsonEncodable;
import net.sourceforge.javajson.JsonObject;
import stock.credentials.NordnetFr;
import stock.credentials.TwoWayLogin;

import com.gargoylesoftware.htmlunit.ElementNotFoundException;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlForm;
import com.gargoylesoftware.htmlunit.html.HtmlPage;

/**
 * @author Filip
 */
public class NordNetDirektDepo extends TimerTask {
    private final TwoWayLogin nordnetFr = new NordnetFr();
    private final long refreshDelay = 5 * 60000l;
    private final long loginTimeout = 20 * 60000l;

    private final Timer timer;
    private final NordNetDirektDepoParser parser;

    private final WebClient client;
    private HtmlPage page;

    private long loginTimestamp = 0;
    private String depoValueCache;
    private List<JsonEncodable> resultCache;
    private final FondDataSheetUpdater sheetUpdate;
    private Calendar lastUpdate;

    public NordNetDirektDepo() {
        resultCache = new ArrayList<>(0);
        parser = new NordNetDirektDepoParser();
        sheetUpdate = new FondDataSheetUpdater();
        timer = new Timer("NordnetTimedLogin");
        client = Helpers.createNewAndSilenceWebClient();

        depoValueCache = "VALUE NOT SET";
        resultCache = new ArrayList<>();
    }

    public void startSchedule() {
        timer.scheduleAtFixedRate(this, 1000, refreshDelay);
    }

    private HtmlPage refreshPage(WebClient client) {
        try {
            if (System.currentTimeMillis() - loginTimestamp >= loginTimeout) {
                System.out.println("Logging in depo parser");
                client = Helpers.createNewAndSilenceWebClient();
                page = client.getPage("https://www.nordnetdirekt.se/");
                final HtmlForm loginFormElement = page.getForms().get(0);
                Thread.sleep(2000);
                loginFormElement.getInputByName("a1").setValueAttribute(
                        nordnetFr.getUser());
                loginFormElement.getInputByName("a2").setValueAttribute(
                        nordnetFr.getPassword());
                loginFormElement.getInputByName("nyckel").setValueAttribute(
                        nordnetFr.getSecondaryPassword());
                /* Submit hack */
                final HtmlButton submitButton = (HtmlButton) page
                        .createElement("button");
                submitButton.setAttribute("type", "submit");
                loginFormElement.appendChild(submitButton);
                return submitButton.click();
            } else {
                return (HtmlPage) page.refresh();
            }
        } catch (IOException | FailingHttpStatusCodeException
                | InterruptedException | ElementNotFoundException ex) {
            throw new RuntimeException("Failed to login onto Nordnet", ex);
        } finally {
            loginTimestamp = System.currentTimeMillis();
        }
    }

    @Override
    public void run() {
        int day = Calendar.getInstance().get(Calendar.DAY_OF_WEEK);
        int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
        if (day != Calendar.SATURDAY && day != Calendar.SUNDAY && hour >= 8
                && hour <= 18 || page == null) {
            lastUpdate = Calendar.getInstance();
            System.out.println("Running depo parser");
            page = refreshPage(client);

            depoValueCache = parser.fetchLatestValue(page);
            resultCache = parser.getDepo(page);
            try {
                resultCache.add(new JsonEncodable() {
                    @Override
                    public void putJSON(JsonObject o) {
                        SimpleDateFormat s = new SimpleDateFormat("HH:mm");
                        o.put("value", parser.fetchLatestRate(page));
                        o.put("latesttime", s.format(lastUpdate.getTime()));
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
            sheetUpdate.update(depoValueCache);
        }
    }

    public Collection<JsonEncodable> getResultCache() {
        return resultCache;
    }

    public String getDepoValueCache() {
        return depoValueCache;
    }
}
